package com.candy.biz.manager;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.candy.biz.domain.dto.SysUserDTO;
import com.candy.biz.domain.entity.SysMenu;
import com.candy.biz.domain.param.SysMenuSaveParam;
import com.candy.biz.domain.vo.SysMenuVO;
import com.candy.biz.enums.MenuTypeEnum;
import com.candy.common.domain.PageVO;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;



/**
 * 菜单权限-通用处理层。
 *
 * @author rong xi
 * @date 2023/09/18 09:18
 * @version 1.0.0
 */
@Component
@AllArgsConstructor
@Slf4j
public class SysMenuManager {

    private static SysMenuManager manager;

    @PostConstruct
    private void init(){
        manager = this;
    }


    /**
     * 菜单权限po对象转菜单权限vo对象
     *
     * @param po po对象
     * @return vo对象
     */
    public static SysMenuVO poToVo(SysMenu po){
        return CommonManager.convert(po, SysMenuVO.class);
    }

    /**
     * 菜单权限分页对象转换分页视图数据
     *
     * @param page 分页结果
     * @return 分页数据
     */
    public static PageVO<SysMenuVO> pageToPageVO(Page<SysMenu> page) {
        //转换处理
        return PageVO.of(posToVos(page.getRecords()),page.getTotalRow());
    }

    /**
     * 菜单权限po集合转菜单权限vo集合
     *
     * @param pos po集合对象
     * @return vos vo集合对象
     */
    public static List<SysMenuVO> posToVos(List<SysMenu> pos){
        return CommonManager.convert(pos, SysMenuVO.class);
    }


    /**
     * 菜单权限po集合转菜单权限树vo集合
     *
     * @param pos po集合对象
     * @return vos 树vo集合对象
     */
    public static List<Tree<Long>> posToTreeList(List<SysMenu> pos){
        List<Long> userIds = pos.stream().map(SysMenu::getCreateUser).collect(Collectors.toList());
        Optional<Map<Long, SysUserDTO>> userInfoMap = SysUserManager.getUserInfoMapOpt(userIds);
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义排序名 都要默认值的
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setWeightKey("orderNum");
        treeNodeConfig.setNameKey("menuName");
        treeNodeConfig.setParentIdKey("parentId");
        // 最大递归深度
        treeNodeConfig.setDeep(5);
        //转换器 (含义:找出父节点为字符串零的所有子节点, 并递归查找对应的子节点, 深度最多为 5)
        return TreeUtil.build(pos, 0L, treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setWeight(treeNode.getOrderNum());
                    tree.setId(treeNode.getId());
                    tree.setName(treeNode.getMenuName());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.setParentId(treeNode.getParentId());
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("typeName", MenuTypeEnum.getRemarkByValue(treeNode.getType()));
                    tree.putExtra("routePath", treeNode.getRoutePath());
                    tree.putExtra("componentPath", treeNode.getComponentPath());
                    tree.putExtra("permissionCode", treeNode.getPermissionCode());
                    tree.putExtra("orderNum", treeNode.getOrderNum());
                    tree.putExtra("delFlag", treeNode.getDelFlag());
                    tree.putExtra("remark", treeNode.getRemark());
                    tree.putExtra("createUser", treeNode.getCreateUser());
                    tree.putExtra("createUserName", userInfoMap.filter(i-> ObjectUtil.isNotNull(treeNode.getId())).filter(CollectionUtil::isNotEmpty).map(m->m.get(treeNode.getCreateUser()).getUserName()));
                    tree.putExtra("createTime", treeNode.getCreateTime());
                    tree.putExtra("updateUser", treeNode.getUpdateUser());
                    tree.putExtra("updateTime", treeNode.getUpdateTime());
                });
    }

    /**
     * 菜单权限po集合转菜单权限树vo集合
     *
     * @param pos po集合对象
     * @return vos 树vo集合对象
     */
    public static List<Tree<String>> posToMenuList(List<SysMenu> pos){
        log.info(JSON.toJSONString(pos));
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义排序名 都要默认值的
        treeNodeConfig.setIdKey("idStr");
        treeNodeConfig.setWeightKey("orderNum");
        treeNodeConfig.setNameKey("title");
        // 最大递归深度
        treeNodeConfig.setDeep(5);
        //转换器 (含义:找出父节点为字符串零的所有子节点, 并递归查找对应的子节点, 深度最多为 5)
        return TreeUtil.build(pos, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setWeight(treeNode.getOrderNum());
                    tree.setId(treeNode.getId().toString());
                    tree.setName(treeNode.getMenuName());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.setParentId(treeNode.getParentId().toString());
                    tree.putExtra("id",treeNode.getRoutePath());
                });
    }

    /**
     * 菜单权限po集合转菜单权限树vo集合
     *
     * @param pos po集合对象
     * @return vos 树vo集合对象
     */
    public static Tree<Long> posToTree(List<SysMenu> pos){
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义排序名 都要默认值的
        treeNodeConfig.setWeightKey("orderNum");
        treeNodeConfig.setNameKey("title");
        // 最大递归深度
        treeNodeConfig.setDeep(5);
        //转换器 (含义:找出父节点为字符串零的所有子节点, 并递归查找对应的子节点, 深度最多为 5)
        Tree<Long> rootTree = TreeUtil.buildSingle(pos, 0L, treeNodeConfig,
                 (treeNode, tree) -> {
                    tree.setWeight(treeNode.getOrderNum());
                    tree.setId(treeNode.getId());
                    tree.setName(treeNode.getMenuName());
                    tree.setParentId(treeNode.getParentId());
                    tree.putExtra("spread",true);
        });
        rootTree.setName("顶级");
        rootTree.putExtra("spread",true);
        return rootTree;
    }


    /**
     * 新增菜单权限准备
     *
     * @param param 新增参数
     * @return po对象
     */
    public static SysMenu insertPrepare(SysMenuSaveParam param){
        SysMenu sysMenu = BeanUtil.copyProperties(param, SysMenu.class);
        sysMenu.setId(IdUtil.getSnowflakeNextId());
        sysMenu.setCreateUser(StpUtil.getLoginIdAsLong());
        sysMenu.setCreateTime(LocalDateTime.now());
        return sysMenu;
    }

    /**
     * 修改菜单权限准备
     *
     * @param param 修改参数
     * @return po对象
     */
    public static SysMenu updatePrepare(SysMenuSaveParam param){
        SysMenu sysMenu = BeanUtil.copyProperties(param, SysMenu.class);
        sysMenu.setUpdateUser(StpUtil.getLoginIdAsLong());
        sysMenu.setUpdateTime(LocalDateTime.now());
        return sysMenu;
    }

}
